﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ce.office.extension;
using NPOI.SS.UserModel;

namespace LView.CMS.Core.Helper
{
    public class HtmlHelper
    {
        private static readonly List<KeyValuePair<HorizontalAlignment, string>> HALIGN = new List<KeyValuePair<HorizontalAlignment, string>>
        {
            new KeyValuePair<HorizontalAlignment, string>(HorizontalAlignment.Left, "left"),
            new KeyValuePair<HorizontalAlignment, string>(HorizontalAlignment.Center, "center"),
            new KeyValuePair<HorizontalAlignment, string>(HorizontalAlignment.Right, "right"),
            new KeyValuePair<HorizontalAlignment, string>(HorizontalAlignment.Fill, "left"),
            new KeyValuePair<HorizontalAlignment, string>(HorizontalAlignment.Justify, "left"),
            new KeyValuePair<HorizontalAlignment, string>(HorizontalAlignment.CenterSelection, "center")
        };

        private static readonly List<KeyValuePair<VerticalAlignment, string>> VALIGN = new List<KeyValuePair<VerticalAlignment, string>>
        {
            new KeyValuePair<VerticalAlignment, string>(VerticalAlignment.Bottom, "bottom"),
            new KeyValuePair<VerticalAlignment, string>(VerticalAlignment.Center, "middle"),
            new KeyValuePair<VerticalAlignment, string>(VerticalAlignment.Top, "top")
        };

        private static readonly List<KeyValuePair<BorderStyle, string>> BORDER = new List<KeyValuePair<BorderStyle, string>>
        {
            new KeyValuePair<BorderStyle, string>(BorderStyle.DashDot, "dashed 1pt"),
            new KeyValuePair<BorderStyle, string>(BorderStyle.DashDotDot, "dashed 1pt"),
            new KeyValuePair<BorderStyle, string>(BorderStyle.Dashed, "dashed 1pt"),
            new KeyValuePair<BorderStyle, string>(BorderStyle.Dotted, "dotted 1pt"),
            new KeyValuePair<BorderStyle, string>(BorderStyle.Double, "double 3pt"),
            new KeyValuePair<BorderStyle, string>(BorderStyle.Hair, "dashed 1px"),
            new KeyValuePair<BorderStyle, string>(BorderStyle.Medium, "solid 2pt"),
            new KeyValuePair<BorderStyle, string>(BorderStyle.MediumDashDot, "dashed 2pt"),
            new KeyValuePair<BorderStyle, string>(BorderStyle.MediumDashDotDot, "dashed 2pt"),
            new KeyValuePair<BorderStyle, string>(BorderStyle.MediumDashed, "dashed 2pt"),
            new KeyValuePair<BorderStyle, string>(BorderStyle.None, "none"),
            new KeyValuePair<BorderStyle, string>(BorderStyle.SlantedDashDot, "dashed 2pt"),
            new KeyValuePair<BorderStyle, string>(BorderStyle.Thick, "solid 3pt"),
            new KeyValuePair<BorderStyle, string>(BorderStyle.Thin, "solid 1pt")
        };

        public static (string, string) GetExcelHtml(IEnumerable<ExcelSheetModel> sheetList)
        {
            Dictionary<string, string> dictionary = new Dictionary<string, string>();
            StringBuilder styleSb = new StringBuilder();
            StringBuilder contentSb = new StringBuilder();
            add(styleSb, "&lt;style&gt;");
            add(styleSb, "        .sheet-content{");
            add(styleSb, "            position: relative;");
            add(styleSb, "            height: 495px;");
            add(styleSb, "            width: 100%;");
            add(styleSb, "            -moz-box-sizing: border-box;");
            add(styleSb, "            -webkit-box-sizing: border-box;");
            add(styleSb, "            box-sizing: border-box;");
            add(styleSb, "            margin: 0;");
            add(styleSb, "            padding: 0;");
            add(styleSb, "            overflow: auto;");
            add(styleSb, "        }");
            add(styleSb, "        .sheet-bar{");
            add(styleSb, "            -moz-box-sizing: border-box;");
            add(styleSb, "            -webkit-box-sizing: border-box;");
            add(styleSb, "            box-sizing: border-box;");
            add(styleSb, "            position:absolute;");
            add(styleSb, "            bottom: 0;");
            add(styleSb, "            left: 0;");
            add(styleSb, "            border-top: 1px solid #ccc;");
            add(styleSb, "            height: 32px;");
            add(styleSb, "            width: 100%;");
            add(styleSb, "            font-size: 0;");
            add(styleSb, "            white-space:nowrap;");
            add(styleSb, "            overflow-x: auto;");
            add(styleSb, "            overflow-y: hidden;");
            add(styleSb, "        }");
            add(styleSb, "        .sheet-bar-item{");
            add(styleSb, "            -moz-box-sizing: border-box;");
            add(styleSb, "            -webkit-box-sizing: border-box;");
            add(styleSb, "            box-sizing: border-box;");
            add(styleSb, "            position: relative;");
            add(styleSb, "            display: inline-block;");
            add(styleSb, "            font-size: 14px;");
            add(styleSb, "            height: 32px;");
            add(styleSb, "            line-height: 32px;");
            add(styleSb, "            padding: 0 16px;");
            add(styleSb, "            border-right:1px solid #ccc;");
            add(styleSb, "            background-color: #f2f2f2;");
            add(styleSb, "            cursor: pointer;");
            add(styleSb, "            color: #666;");
            add(styleSb, "        }");
            add(styleSb, "        .sheet-bar-item.active{");
            add(styleSb, "            background-color: #fff;");
            add(styleSb, "            color: #04BCC1;");
            add(styleSb, "        }");
            add(styleSb, "        .sheet-bar-item.active:after {");
            add(styleSb, "            position: absolute;");
            add(styleSb, "            left: 0;");
            add(styleSb, "            bottom: 0;");
            add(styleSb, "            content: '';");
            add(styleSb, "            width: 100%;");
            add(styleSb, "            height: 4px;");
            add(styleSb, "            box-sizing: border-box;");
            add(styleSb, "            pointer-events: none;");
            add(styleSb, "            border-bottom: 4px solid #04BCC1;");
            add(styleSb, "        }");
            add(styleSb, "        .sheet-content-item{");
            add(styleSb, "            position: relative;");
            add(styleSb, "            height: 100%;");
            add(styleSb, "            width: 100%;");
            add(styleSb, "            -moz-box-sizing: border-box;");
            add(styleSb, "            -webkit-box-sizing: border-box;");
            add(styleSb, "            box-sizing: border-box;");
            add(styleSb, "            overflow: auto;");
            add(styleSb, "            display: none;");
            add(styleSb, "        }");
            add(styleSb, "        .sheet-content-item.show{");
            add(styleSb, "            display: block;");
            add(styleSb, "        }");
            add(styleSb, "        td{");
            add(styleSb, "            height: 13.5pt;");
            add(styleSb, "            font-size: 11pt;");
            add(styleSb, "            white-space: pre;");
            add(styleSb, "            color:#000;");
            add(styleSb, "        }");
            add(styleSb, "        .ftr&gt;td{");
            add(styleSb, "            height: 0;");
            add(styleSb, "        }");
            add(styleSb, "        .right{");
            add(styleSb, "            text-align: right;");
            add(styleSb, "        }");
            add(styleSb, "        .center{");
            add(styleSb, "            text-align: center;");
            add(styleSb, "        }");
            add(styleSb, "{$style}");
            add(styleSb, "    &lt;/style&gt;");

            add(contentSb, "    &lt;div class=\"sheet-content\" &gt;");
            string text = "";
            int num = 0;
            foreach (ExcelSheetModel sheet in sheetList)
            {
                text += "&lt;div class=\"sheet-bar-item";
                if (num == 0)
                {
                    text += " active ";
                }

                text = text + "\" data-value=\"" + sheet.Id + "\"  &gt;" + sheet.Name + "&lt;/div&gt;";
                add(contentSb, "<" + "div class=\"sheet-content-item " + ((num == 0) ? "show" : "") + " \" id =\"" + sheet.Id + "\" &gt;" + GetSheetHtml(sheet, dictionary) + "<" + "/div" + ">");
                num++;
            }

            add(contentSb, "    &lt;/div&gt;");
            add(contentSb, "    &lt;div class=\"sheet-bar\" &gt;");
            add(contentSb, "        " + text);
            add(contentSb, "    &lt;/div&gt;");
            add(contentSb, "    &lt;script&gt;");
            add(contentSb, "        window.onload = function(){");
            add(contentSb, "            var btnlist = document.querySelectorAll('.sheet-bar-item');");
            add(contentSb, "            for(var i = 0,l =btnlist.length;i&lt;l;i++){");
            add(contentSb, "                btnlist[i].onclick=function () {");
            add(contentSb, "                    var sheetId = this.getAttribute('data-value');");
            add(contentSb, "                    if(this.className.indexOf('active') == -1){");
            add(contentSb, "                        document.getElementsByClassName('active')[0].className = 'sheet-bar-item';");
            add(contentSb, "                        this.className = 'sheet-bar-item active';");
            add(contentSb, "                        document.getElementsByClassName('show')[0].className = 'sheet-content-item';");
            add(contentSb, "                        document.getElementById(sheetId).className = 'sheet-content-item show';");
            add(contentSb, "                    }");
            add(contentSb, "                }");
            add(contentSb, "            }");
            add(contentSb, "        }");
            add(contentSb, "    &lt;/script&gt;");
            //add("</body>");
            //add("</html>");
            string text2 = "";
            foreach (KeyValuePair<string, string> item in dictionary)
            {
                text2 = text2 + "        ." + item.Value + "{" + item.Key + "}\r\n";
            }

            string text3 = contentSb.ToString();
            string text4 = styleSb.ToString();
            return (text3, text4.Replace("{$style}", text2));
            void add(StringBuilder sb, string str)
            {
                sb.Append(str + "\r\n");
            }
        }

        public static string GetSheetHtml(ExcelSheetModel sheet, Dictionary<string, string> classMap)
        {
            StringBuilder sb = new StringBuilder();
            add("<table cellspacing=\"0\" cellpadding=\"0\" style=\"border-collapse:collapse;table-layout:fixed;width:" + sheet.TableWidth.ToString() + "px;\"  >");
            add("<tr class=\"ftr\">");
            foreach (decimal cellWidth in sheet.CellWidths)
            {
                add("<td style=\"" + GetPXStyle("width", cellWidth) + "\"></td>");
            }

            add("</tr>");
            foreach (ExcelRowModel row in sheet.Rows)
            {
                add("<tr>");
                foreach (ExcelCellModel cell in row.Cells)
                {
                    string style = GetStyle(cell);
                    string text = "";
                    if (!string.IsNullOrEmpty(style))
                    {
                        string text2 = "c" + classMap.Count.ToString();
                        if (classMap.ContainsKey(style))
                        {
                            text2 = classMap[style];
                        }
                        else
                        {
                            classMap.Add(style, text2);
                        }

                        text = "class=\"" + text2 + "\"";
                    }

                    add(string.Format("<td {0}{1}{2}>{3}</td>", text, GetRowColSpan("rowspan", cell.RowSpan), GetRowColSpan("colspan", cell.ColumnSpan), cell.Text));
                }

                add("</tr>");
            }

            add("</table>");
            return sb.ToString();
            void add(string str)
            {
                sb.Append(str + "\r\n");
            }
        }

        private static string GetRowColSpan(string type, int span)
        {
            if (span == 1)
            {
                return "";
            }

            return $" {type}=\"{span}\"";
        }

        private static string GetPXStyle(string k, decimal w)
        {
            return k + ":" + w.ToString() + "px;";
        }

        private static string GetStyle(ExcelCellModel cell)
        {
            string str = "";
            str += StyleOut("text-align", cell.Alignment, cell.CellType);
            str += StyleOut("vertical-align", cell.VerticalAlignment);
            str += StyleOut("border-left", cell.BorderLeft, cell.BorderLeftColor);
            str += StyleOut("border-right", cell.BorderRight, cell.BorderRightColor);
            str += StyleOut("border-top", cell.BorderTop, cell.BorderTopColor);
            str += StyleOut("border-bottom", cell.BorderBottom, cell.BorderBottomColor);
            str += StyleOut(cell.WrapText);
            str += SetHeight(cell.HeightInPoints);
            if (cell.Font != null)
            {
                str += SetFontWeight(cell.Font.Boldweight, cell.Font.IsBold);
                str += SetFontSize(cell.Font.FontHeightInPoints);
                str += SetFontItalic(cell.Font.IsItalic);
                str += SetFontFamily(cell.Font.FontName);
            }

            str += SetFillColor(cell.FillColor);
            return str + SetFontColor(cell.FontColor);
        }

        private static string StyleOut(string k, HorizontalAlignment p, CellType cellType)
        {
            if (p == HorizontalAlignment.General)
            {
                string text = "";
                switch (cellType)
                {
                    case CellType.Boolean:
                    case CellType.Error:
                        text = "text-align:center;";
                        break;
                    case CellType.Numeric:
                        text = "text-align:right;";
                        break;
                    default:
                        text = "";
                        break;
                }

                return text;
            }

            return k + ":" + HALIGN.Where((KeyValuePair<HorizontalAlignment, string> o) => o.Key == p).First().Value + ";";
        }

        private static string StyleOut(string k, VerticalAlignment p)
        {
            return k + ":" + VALIGN.Where((KeyValuePair<VerticalAlignment, string> o) => o.Key == p).First().Value + ";";
        }

        private static string StyleOut(string k, BorderStyle p, string color)
        {
            if (p == BorderStyle.None)
            {
                return "";
            }

            string str = k + ":" + BORDER.Where((KeyValuePair<BorderStyle, string> o) => o.Key == p).First().Value;
            if (!string.IsNullOrEmpty(color))
            {
                str = str + " " + color;
            }

            return str + ";";
        }

        private static string StyleOut(bool isWrapText)
        {
            if (isWrapText)
            {
                return "white-space:pre-wrap;";
            }

            return "";
        }

        private static string SetHeight(float h)
        {
            if (h == 0f)
            {
                return "";
            }

            return "height:" + h.ToString() + "pt;";
        }

        private static string SetFontWeight(short w, bool isBold)
        {
            if (isBold)
            {
                return "font-weight:bold;";
            }

            if (w == 400)
            {
                return "";
            }

            return "font-weight:" + w.ToString() + ";";
        }

        private static string SetFontSize(double size)
        {
            if (size == 11.0)
            {
                return "";
            }

            return "font-size:" + size.ToString() + "pt;";
        }

        private static string SetFontItalic(bool isItalic)
        {
            if (isItalic)
            {
                return "font-style:italic;";
            }

            return "";
        }

        private static string SetFontFamily(string FontName)
        {
            if (!string.IsNullOrEmpty(FontName))
            {
                return "font-family:" + FontName + ";";
            }

            return "";
        }

        private static string SetFillColor(string color)
        {
            if (!string.IsNullOrEmpty(color))
            {
                return "background-color:" + color + ";";
            }

            return "";
        }

        private static string SetFontColor(string color)
        {
            if (string.IsNullOrEmpty(color) || color == "#000000")
            {
                return "";
            }

            return "color:" + color + ";";
        }
    }
}
